package consultas;

import interfazGrafica.Grafo.Arista;
import interfazGrafica.Grafo.Punto;

import java.awt.Color;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Set;

import javax.swing.JOptionPane;

import estructuraGrafo.Enlace;
import estructuraGrafo.Grafo;
import estructuraGrafo.Nodo;

/**
 * Clase ConsultaC: Clase para realizar la consulta del item 5.C
 * 
 * @author  Grupo N11
 * @author  Prinsich Bernz, Emilio J. A.
 * @author 	Solia, Guillermo D.
 * @version  1.0
 */

//Busqueda en anchura
public class ConsultaC implements Serializable{

	private static final long serialVersionUID = 1L;
	/**Lista de Enlaces recoridos*/
	private static Set<Enlace> listaEnlaces;
	/**Lista de Nodos recorridos*/
	private static Set<Nodo> listaNodos;
	
	/**Constructor*/
	public ConsultaC(){
		listaEnlaces = new LinkedHashSet<Enlace>();
		listaNodos = new LinkedHashSet<Nodo>();
	}
	
	/**
	 * A partir de una busqueda en achura recorre todos los nodos desde un punto
	 * @param graph Garfo a Recorrer
	 * @return Lista de Nodos Recorridos
	 */
	public Set<Nodo> consultar(Grafo graph){
		Object[] possibleValues = new Object[graph.getNombres().size()];
		for(int i = 0; i < graph.getNombres().size(); i++)
			possibleValues[i] = graph.getNombres().get(i);
		
		String inicio = "#";
		do{//Solicita al usuario que ingrese el nodo de inicio de la busqueda y verifica de que existan
			inicio = (String) JOptionPane.showInputDialog(null, "Que tipo de nodo desea que sea?",
					"Tipo de nodo", JOptionPane.INFORMATION_MESSAGE, null,
					possibleValues, possibleValues[0]);
			if(inicio.equals(""))
				break;
			else if(!graph.getNombres().contains(inicio)){
				JOptionPane.showMessageDialog(null,"El peaje no existe, por favor ingrese otro","Peaje Inexistente", JOptionPane.ERROR_MESSAGE );
				inicio = "#"; 
			}
		}while(inicio.equals("#"));
				
		//Busca el nodo ingresado en el Grafo 
		Nodo node = graph.getNodos().get(inicio);

		// cola con los nodos a visitar
		Queue<Nodo> aVisitar = new LinkedList<Nodo>();
		aVisitar.offer(node);
		//realiza la busqueda en achura
		while(!aVisitar.isEmpty()){
			Nodo n = aVisitar.poll();
			//encolar los adyacentes
			Set<Nodo> adyacentes = listarAdyacentes(n, graph);
			for(Nodo adyacente: adyacentes ){
				if(!listaNodos.contains(adyacente)){
					aVisitar.offer(adyacente);
				}
			}			
			listaNodos.add(n);
		}
		return listaNodos; 
	}
	
	/**
	 * Lista los Nodos Adyasentes a un nodo
	 * @param n Nodo
	 * @param g Grafo
	 * @return Lista de Nodos Adyasentes a n
	 */
	private Set<Nodo> listarAdyacentes(Nodo n, Grafo g) {
		
		Set<Nodo> listaAdyacentes = new LinkedHashSet<Nodo>();
		for(Enlace link : n.getEnlaces()){
			if(link.isEstado()){
				Nodo node = g.getNodos().get(link.getDestino());
				listaAdyacentes.add(node);
				listaEnlaces.add(link);
			}
		}
		return listaAdyacentes;
	}
	
	/**
	 * Muesta en un String el resultado de la consulta C
	 * @param graph Grafos
	 * @return String de la consullta
	 */
	public String getText(Grafo graph){
		String tmp = "Desde: ";
		Set<Nodo> node = consultar(graph);
		boolean t = true;
		for(Nodo n : node){
			if(t){
				if(n.getTipo() == 0)
					tmp = tmp + n.getNombre() + " - Acceso Norte\n>";
				else
					tmp = tmp + n.getNombre() + "\nHasta los peajes: \n>";
				t = false;
			} else{
				if(n.getTipo() == 1){
					tmp = tmp + n.getNombre() + " - Salida Sur\n";
					for(Enlace l : listaEnlaces)
						if(l.getDestino().equals(n.getNombre()))
							tmp = tmp + "Por la Avenida: " + l.getNombre() + "\n";
					tmp = tmp + ">";
				}
				else{
					tmp = tmp + n.getNombre() + "\n";
					for(Enlace l : listaEnlaces)
						if(l.getDestino().equals(n.getNombre()))
							tmp = tmp + "Por la Avenida: " + l.getNombre() + "\n";
					tmp = tmp + ">";
				}
			}
		}
		return tmp;
	}
	
	/**
	 * Pinta el grafo que esta en el Linezo
	 * @param aristas Arista que representan los enlaces
	 * @param puntos Puntos que representan los nodos
	 */
	public void pintar(ArrayList<Arista> aristas, ArrayList<Punto> puntos){
		boolean t = true;
		
		//Pinta las Aristas
		for(Enlace link : listaEnlaces){
			for(Arista aris : aristas){
				if(aris.getNombre().equals(link.getNombre())){
					aris.setColor(Color.RED);
				}
			}
		}
		//Pinta los Nodos
		for(Nodo node : listaNodos){
			for(Punto point : puntos){
				if(point.getNombre().equals(node.getNombre())){
					if(t){
						point.setColorPunto(Color.RED);
						t = false;
					}
					else
						point.setColorPunto(Color.GREEN);
				}
			}
		}
	}
}
